#pragma once

#include "objfactory.h"
#include "thread_pool.h"
#include "core.hpp"
#include "logger.h"
#include "network.h"
#include "parser.h"
#include "kv.h"
#include "lock.h"
// #include "participant.h"
// #include "coordinator.h"
#include "GLOBAL.h"
#include "utils.h"
// #include "threadpool.hpp"

namespace raft
{
    // template <typename T>
    class server : public noncopyable
    {
    
    private:
        // follower
        // the local txid
        txid                _TXID;

        // network
        Network             _net;

        // the log
        Logger              _lg;

        // kv
        KV                  _kvdb;

        // helper
        Parser              _parser;
        // leader

        // the state of the coordinator

        // the network of the coordinator
        // Network                             _cnet;

        std::thread                         _workThread;
        // std::thread                         _recoveryThread;
        // the participant keepalive list
        std::thread                         _talive[MAX_THREAD_NUMBER];
        std::thread                         _tworking[MAX_THREAD_NUMBER];
        std::thread                         _tsendThread[MAX_THREAD_NUMBER];
        std::thread                         _tvoteThread[MAX_THREAD_NUMBER];
        std::thread _fkeep;
        std::thread _fwork;
    public:
        void Init(std::vector<NodeInfo> ps, NodeInfo c);
        int Launch();
        void KVPrint();
    private:
        // follower
        int followerpKeepAlive();
        int followerWorking();

        std::string pWorker(std::string task);
        std::string eventParser(std::string event);
        void LogToKVStore();
        
        // leader
        // int Recovery();
        int Working();

        void work();
        // void recovery();
        // void LeaderpWorking(int id);
        void LeaderpKeepAlive(int id);
        // void pRecovery(p_id id);

    //server
        
    private:
        // std::mutex m_mutex;
        exclusiveLock                       _logMutex;
        exclusiveLock                       _workingMutex;
        exclusiveLock                       _raftMutex;
        //这里的 objfactory<server> 是一个模板类，负责创建和管理 server 类型的对象。
        std::shared_ptr<objfactory<server>> m_factory;
        // 对象池
        // 线程池
        // std::shared_ptr<T> = m_factory->Get(m_id, m_factory);
        raft::thread_pool &tpool = raft::thread_pool::get(100);
        // ThreadPool *pool;

        int m_id;          // server_id
        int _fnum;         // follower num, include self
        // CState                _cstate;
        // the participant state table
        // std::map<int, std::atomic<State>>_pstate;// atomic 保证原子性
        std::map<p_id, std::atomic<P_State>>_pstate;           // if aliveable
        // the participant network;
        std::map<int, Network>             _pnet;
        // the participant info
        std::map<p_id, NodeInfo>            _pinfo;

        bool m_is_stop = true; // 停服
        int m_heartbeat = 0;   // 心跳超时计数
        int m_vote_count = 0;  // 拥有的投票数

        // 需要持久化的数据
        // State m_state = State::None; 
        State m_state;// 状态
        int m_term = 0;              // 任期
        int m_votedfor = 0;          // 给谁投票
        std::vector<Log> m_log_vec;  // 日志

        // 临时数据
        int m_commit_index = 0; // 自己的提交进度索引
        int m_last_applied = 0; // 自己的保存进度索引

        // 只属于leader的临时数据
        std::vector<int> m_next_index_vec;  // 所有serve将要同步的进度索引
        std::vector<int> m_match_index_vec; // 所有server已经同步的进度索引

    public:
        server() = delete;
        server(int id, std::shared_ptr<objfactory<server>> factory);
        ~server() = default;

        int key() const { return m_id; }
        bool IsLeader() const { return m_state == State::Leader; }
        int Term() const { return m_term; }
        State GetState() const { return m_state; }
        bool IsStop() const { return m_is_stop; }
        const std::vector<Log> &LogVec() const { return m_log_vec; }
        const std::vector<Log> ApplyLogVec();//1

        int AddLog(const std::string &str); // 添加日志
        std::string Request(std::string task); // 处理请求

        void Start(std::vector<NodeInfo> ps, NodeInfo c);
        void Stop();
        void ReStart();

    private:
        void Update();   // 定时器
        void Election(); // 选举

        // network
        // vote
        void ReplyVote(const VoteReply &reply);
        VoteReply RequestVoteAndReply(const VoteArgs &args);

       // AppendEntries
        void SendAppendEntriesAndReply(); // == Election
        AppendEntriesReply RecvAppendEntriesAndReply(const AppendEntriesArgs &args);
        
        // void SendVoteArgsAndReply(const VoteArgs &args);

        void check_election_timeout();
        void RequestAppendEntries(const AppendEntriesArgs &args);
        void ReplyAppendEntries(const AppendEntriesReply &reply);

        void ToLeader();
        void ToFollower(int term, int votedfor);

        // Print
    private:
        std::map<long long, std::queue<std::string>> m_print_map;

    public:
        void Print();
        void AddPrint(const std::string &str);
        void PrintAllLog();
        void PrintAllApplyLog();
        void serverStart(int id);
    };

}
